package com.simple.trade.holder;

import com.google.common.base.Preconditions;
import com.simple.common.entity.ReqContext;
import com.simple.common.entity.po.sys.*;
import com.simple.ds.service.ApiContextService;
import com.simple.ds.service.ChannelService;
import com.simple.ds.service.ExampleChannelApi;
import com.simple.ds.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 支付的上下文
 *
 * @author yasud
 * @date 2020年09月29日 14:38
 * @description
 */
@Component
public class PayContext {

    /**
     * 建立一个线程变量
     */
    private ThreadLocal<ReqContext> THREAD_LOCAL = new InheritableThreadLocal();

    private ThreadLocal<Product> THREAD_LOCAL_PRODUCT = new InheritableThreadLocal();

    private ThreadLocal<ChannelComp> THREAD_LOCAL_CHANNEL = new InheritableThreadLocal();

    private ThreadLocal<ExampleChannel> THREAD_LOCAL_EXP_C = new InheritableThreadLocal();

    /**
     * 新建一个静态变量存自己
     */
    private static PayContext PAY_CONTEXT;

    @Autowired
    ApiContextService apiContextService;

    @Autowired
    ChannelService channelService;

    @Autowired
    ProductService productService;

    @Autowired
    ExampleChannelApi exampleChannelApi;

    @Autowired
    public void init() {
        PAY_CONTEXT = this;
    }

    /**
     * 返回当前支付的上下文
     *
     * @return
     */
    public static PayContext current() {
        return PAY_CONTEXT;
    }

    /**
     * 每次都会被拦截器调用
     */
    public void iam(String appId, String pCode) {
        ReqContext reqContext = apiContextService.getFullContextByAppId(appId);
        Product product = productService.chooseProduct(pCode, reqContext.getExample().getId());
        Map<String, Object> pair = channelService.chooseChannelByExpId(reqContext.getExample().getId(), product);
        ChannelComp channelComp = (ChannelComp) pair.get("left");
        ExampleChannel exampleChannel = (ExampleChannel) pair.get("right");
        Preconditions.checkNotNull(channelComp, "渠道不能为空请检查配置");
        THREAD_LOCAL.set(reqContext);
        THREAD_LOCAL_PRODUCT.set(product);
        THREAD_LOCAL_CHANNEL.set(channelComp);
        THREAD_LOCAL_EXP_C.set(exampleChannel);
    }

    /**
     * hhh
     * @param trade
     */
    public void iam(Trade trade) {
        ReqContext reqContext = apiContextService.getFullContextByAppId(trade.getAppId());
        Product product = productService.findProductByTrade(trade);
        ChannelComp channelComp = channelService.findChannel(trade.getChannelMerchantId());
        ExampleChannel exampleChannel = exampleChannelApi.build(trade);
        Preconditions.checkNotNull(channelComp, "渠道不能为空请检查配置");
        THREAD_LOCAL.set(reqContext);
        THREAD_LOCAL_PRODUCT.set(product);
        THREAD_LOCAL_CHANNEL.set(channelComp);
        THREAD_LOCAL_EXP_C.set(exampleChannel);
    }

    /**
     * 使用完毕清理
     */
    public void clear() {
        THREAD_LOCAL.remove();
        THREAD_LOCAL_PRODUCT.remove();
        THREAD_LOCAL_CHANNEL.remove();
        THREAD_LOCAL_EXP_C.remove();
    }

    /**
     * 当前商户
     *
     * @return
     */
    public Merchant merchant() {
        ReqContext reqContext = THREAD_LOCAL.get();
        Merchant merchant = reqContext.getMerchant();
        Preconditions.checkNotNull(merchant, "当前商户为空, 请检查appId, 数据是否有效");
        return merchant;
    }

    /**
     * 当前app
     *
     * @return
     */
    public Application app() {
        ReqContext reqContext = THREAD_LOCAL.get();
        Application app = reqContext.getApp();
        Preconditions.checkNotNull(app, "当前app为空, 请检查数据是否有效");
        return app;
    }

    /**
     * 当前实例
     *
     * @return
     */
    public AppExample exp() {
        ReqContext reqContext = THREAD_LOCAL.get();
        AppExample example = reqContext.getExample();
        Preconditions.checkNotNull(example, "当前实例为空, 请检查数据是有有效");
        return example;
    }

    /**
     * 当前产品
     * @return
     */
    public Product product() {
        Product product = THREAD_LOCAL_PRODUCT.get();
        Preconditions.checkNotNull(product, "当前实例为空, 请检查数据是有有效");
        return product;
    }

    /**
     * 当前渠道
     * @return
     */
    public ChannelComp channel() {
        ChannelComp channelComp = THREAD_LOCAL_CHANNEL.get();
        Preconditions.checkNotNull(channelComp, "当前实例为空, 请检查数据是有有效");
        return channelComp;
    }

    /**
     * 当前匹配的实例渠道
     * @return
     */
    public ExampleChannel expChannel() {
        ExampleChannel expChannel = THREAD_LOCAL_EXP_C.get();
        Preconditions.checkNotNull(expChannel, "当前实例为空, 请检查数据是有有效");
        return expChannel;
    }

    /**
     * 当前ReqContext
     *
     * @return
     */
    public ReqContext getContext() {
        return THREAD_LOCAL.get();
    }
}
